;;;; auth takes no effect for inproc protocal and it's reasonable.

(in-package :easy-zeromq-tests)


(define-test pull/push         :parent zeromq)
(define-test streamer          :parent zeromq)
(define-test router/dealer     :parent zeromq) ; will not handle the replied msg
(define-test req/rep           :parent zeromq)
(define-test req-router/dealer :parent zeromq) ; will handle the replied msg


(defparameter *msg-stack* nil
  "The byte array will be pushed into this stack as soon as message-handler receives a new msg")

(defparameter *msg-stack-lock* (bt:make-lock))

(defparameter *server-auth-bytes* (easy-zeromq::gen-server-auth :type :bytes))
(defparameter *server-auth-string* (easy-zeromq::gen-server-auth :type :string))

(defparameter *client-auth-bytes* (easy-zeromq::gen-client-auth (easy-zeromq::server-auth-config-server-public-key *server-auth-bytes*)
                                                           :type :bytes))
(defparameter *client-auth-string* (easy-zeromq::gen-client-auth (easy-zeromq::server-auth-config-server-public-key *server-auth-string*)
                                                            :type :string))
(defparameter *client-wrong-auth-bytes*  (easy-zeromq::gen-client-auth (pzmq:curve-keypair) :type :bytes))
(defparameter *client-wrong-auth-string* (easy-zeromq::gen-client-auth (pzmq:curve-keypair-string) :type :string))


(defun message-handler (lisp-byte-vector)
  "handle a message of byte vector of lisp,
will make a printing and push this byte vector to a stack."
  (log:info "Handling new message <~s>" lisp-byte-vector)
  (bt:with-lock-held (*msg-stack-lock*)
    (push lisp-byte-vector *msg-stack*)))

(defun dealer-message-handler-reply (recv-socket lisp-msg-bytes identity empty-frame)
  "handle a message of byte vector of lisp,
will make a printing and push this byte vector to a stack."
  (log:info "Handling new message <~s>" lisp-msg-bytes)
  (bt:with-lock-held (*msg-stack-lock*)
    (push lisp-msg-bytes *msg-stack*)
    (easy-zeromq::dealer-reply-bytes recv-socket identity empty-frame lisp-msg-bytes)))

(defun rep-message-handler-reply (lisp-msg-bytes)
  "handle a message of byte vector of lisp,
will make a printing and push this byte vector to a stack,
and return the bytes finally.
the returned bytes will be used by the rep server as the reply message."
  (log:info "Handling new message <~s>" lisp-msg-bytes)
  (bt:with-lock-held (*msg-stack-lock*)
    (push lisp-msg-bytes *msg-stack*)
    lisp-msg-bytes))

(defun replied-msg-handler (lisp-msg-bytes)
  "used by the req client or dealer client to deal with the replied msg of byte vector."
  (easy-zeromq::decode lisp-msg-bytes))


(easy-zeromq::defencoding %test-encoding-class a b)
(easy-zeromq::defencoding %test-encoding-struct a b)

(define-test gen-server-auth :parent zeromq
  (let ((auth-default (easy-zeromq::gen-server-auth))
        (auth-bytes (easy-zeromq::gen-server-auth :type :bytes))
        (auth-string (easy-zeromq::gen-server-auth :type :string)))
    (of-type easy-zeromq::server-auth-config auth-default)
    (of-type easy-zeromq::server-auth-config auth-bytes)
    (of-type easy-zeromq::server-auth-config auth-string)
    (fail (easy-zeromq::gen-server-auth :type :str))))

(define-test gen-client-auth :parent zeromq
  (let* ((srv-pub (pzmq:curve-keypair))
         (auth-default (easy-zeromq::gen-client-auth srv-pub))
         (auth-bytes (easy-zeromq::gen-client-auth srv-pub :type :bytes))
         (auth-string (easy-zeromq::gen-client-auth srv-pub :type :string)))
    (of-type easy-zeromq::client-auth-config auth-default)
    (of-type easy-zeromq::client-auth-config auth-bytes)
    (of-type easy-zeromq::client-auth-config auth-string)
    (fail (easy-zeromq::gen-client-auth srv-pub :type :str))))


;; --- pull/push ---

(define-test pull/push-tcp-single-endpoint-auth-nil :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-ipc-single-endpoint-auth-nil :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-inproc-single-endpoint-auth-nil :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

;; auth bytes type

(define-test pull/push-tcp-single-endpoint-auth-bytes :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-ipc-single-endpoint-auth-bytes :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-inproc-single-endpoint-auth-bytes :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

;; auth string type

(define-test pull/push-tcp-single-endpoint-auth-string :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-ipc-single-endpoint-auth-string :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test pull/push-inproc-single-endpoint-auth-string :parent pull/push
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))


;; multiple endpoints

(define-test pull/push-tcp-multi-endpoints-auth-nil :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test pull/push-ipc-multi-endpoints-auth-nil :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test pull/push-inproc-multi-endpoints-auth-nil :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))

(define-test pull/push-tcp-multi-endpoints-auth-bytes :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (format t "~&error may occurs here, 0~%")
                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (format t "~&error may occurs here, 1~%")
                    (handler-bind ((error (lambda (c)
                                            (trivial-backtrace:print-backtrace c :output *error-output*))))
                        (easy-zeromq::push-object endpoint struct-obj client-auth))
                    (format t "~&object has been pushed~%")
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::handler-decode (pop *msg-stack*))))
                      (when (eql struct nil)
                        (format t "~&handler-decode returns nil~%")
                        (sleep 1)
                        (setf struct (easy-zeromq::handler-decode (pop *msg-stack*)))
                        (format t "sleep 1 sec, decoded to: ~d" struct))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (format t "~&error may occurs here, 2~%")
                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (format t "~&error may occurs here, 3~%")
                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    (format t "~&error may occurs here, 4~%")
                    ))))

(define-test pull/push-ipc-multi-endpoints-auth-bytes :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test pull/push-inproc-multi-endpoints-auth-bytes :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))

(define-test pull/push-tcp-multi-endpoints-auth-string :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test pull/push-ipc-multi-endpoints-auth-string :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test pull/push-inproc-multi-endpoints-auth-string :parent pull/push
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Pull server listens: ~s~%" listens)
    (format t "~%Push client endpoint: ~d~%" endpoints)
    (easy-zeromq::start-pull-server #'message-handler listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))


;; --- streamer-pull/push ---

(define-test streamer-pull/push-tcp-single-endpoint-auth-nil :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-ipc-single-endpoint-auth-nil :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-inproc-single-endpoint-auth-nil :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

;; auth bytes type

(define-test streamer-pull/push-tcp-single-endpoint-auth-bytes :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-ipc-single-endpoint-auth-bytes :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-inproc-single-endpoint-auth-bytes :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

;; auth string type

(define-test streamer-pull/push-tcp-single-endpoint-auth-string :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-ipc-single-endpoint-auth-string :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))

(define-test streamer-pull/push-inproc-single-endpoint-auth-string :parent streamer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::push-string endpoints str client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-bytes endpoints bytes client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::push-object endpoints class-obj client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::push-object endpoints struct-obj client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::push-string endpoints str client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::push-string endpoints str nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-push-client (sender endpoints client-auth)
      (pzmq:send sender str))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
    ))


;; multiple endpoints

(define-test streamer-pull/push-tcp-multi-endpoints-auth-nil :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-ipc-multi-endpoints-auth-nil :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-inproc-multi-endpoints-auth-nil :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))

(define-test streamer-pull/push-tcp-multi-endpoints-auth-bytes :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-ipc-multi-endpoints-auth-bytes :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-inproc-multi-endpoints-auth-bytes :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))

(define-test streamer-pull/push-tcp-multi-endpoints-auth-string :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-ipc-multi-endpoints-auth-string :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::push-string endpoint str client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::push-bytes endpoint bytes client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::push-object endpoint class-obj client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::push-object endpoint struct-obj client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::push-string endpoint str client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-push-client (sender endpoint client-auth)
                      (pzmq:send sender str))
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                    ))))

(define-test streamer-pull/push-inproc-multi-endpoints-auth-string :parent streamer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Streamer pull server listens: ~s~%" listens)
    (format t "~%Streamer push client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-streamer-pull-server #'message-handler listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::push-string endpoint str client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::push-bytes endpoint bytes client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::push-object endpoint class-obj client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::push-object endpoint struct-obj client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::push-string endpoint str client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-push-client (sender endpoint client-auth)
                       (pzmq:send sender str))
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                     ))))


;;; --- router/dealer ---

(define-test router/dealer-tcp-single-endpoint-auth-nil :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-ipc-single-endpoint-auth-nil :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-inproc-single-endpoint-auth-nil :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

;; auth bytes type

(define-test router/dealer-tcp-single-endpoint-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-ipc-single-endpoint-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-inproc-single-endpoint-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

;; auth string type

(define-test router/dealer-tcp-single-endpoint-auth-string :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-ipc-single-endpoint-auth-string :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))

(define-test router/dealer-inproc-single-endpoint-auth-string :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port)) ; string
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str nil client-auth)
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-bytes endpoints bytes nil client-auth)
    (sleep 0.01)
    (is equalp bytes (pop *msg-stack*))

    (easy-zeromq::dealer-send-object endpoints class-obj nil client-auth)
    (sleep 0.01)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (easy-zeromq::dealer-send-object endpoints struct-obj nil client-auth)
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (easy-zeromq::dealer-send-string endpoints str nil client-wrong-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::dealer-send-string endpoints str nil nil)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))


;; multiple endpoints

(define-test router/dealer-tcp-multi-endpoints-auth-nil :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-ipc-multi-endpoints-auth-nil :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-inproc-multi-endpoints-auth-nil :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                       (pzmq:send sender str)
                       (sleep 0.1)
                       (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                       (pzmq:with-message msg
                         (pzmq:msg-recv msg sender)
                         (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                     ))))

(define-test router/dealer-tcp-multi-endpoints-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-ipc-multi-endpoints-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-inproc-multi-endpoints-auth-bytes :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                       (pzmq:send sender str)
                       (sleep 0.1)
                       (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                       (pzmq:with-message msg
                         (pzmq:msg-recv msg sender)
                         (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                     ))))

(define-test router/dealer-tcp-multi-endpoints-auth-string :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-ipc-multi-endpoints-auth-string :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                    (sleep 0.1)
                    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                    (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                    (sleep 0.1)
                    (is equalp bytes (pop *msg-stack*))

                    (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                    (sleep 0.1)
                    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type  %test-encoding-class class)
                      (is =     (a class) (a class-obj))
                      (is equal (b class) (b class-obj)))

                    (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                    (sleep 0.01)
                    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                      (of-type %test-encoding-struct struct)
                      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                    (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                    (sleep 0.1)
                    (is eql nil (pop *msg-stack*))

                    (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                      (pzmq:send sender str)
                      (sleep 0.1)
                      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                      (pzmq:with-message msg
                        (pzmq:msg-recv msg sender)
                        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                    ))))

(define-test router/dealer-inproc-multi-endpoints-auth-string :parent router/dealer
  (let* ((workers 4)
         (num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn  (easy-zeromq::dealer-send-string endpoint str nil client-auth)
                     (sleep 0.01)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::dealer-send-bytes endpoint bytes nil client-auth)
                     (sleep 0.01)
                     (is equalp bytes (pop *msg-stack*))

                     (easy-zeromq::dealer-send-object endpoint class-obj nil client-auth)
                     (sleep 0.01)
                     (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type  %test-encoding-class class)
                       (is =     (a class) (a class-obj))
                       (is equal (b class) (b class-obj)))

                     (easy-zeromq::dealer-send-object endpoint struct-obj nil client-auth)
                     (sleep 0.01)
                     (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                       (of-type %test-encoding-struct struct)
                       (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                       (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

                     (easy-zeromq::dealer-send-string endpoint str nil client-wrong-auth)
                     (sleep 0.1)
                     (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

                     (easy-zeromq::with-dealer-client (sender endpoint client-auth)
                       (pzmq:send sender str)
                       (sleep 0.1)
                       (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
                       (pzmq:with-message msg
                         (pzmq:msg-recv msg sender)
                         (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
                     ))))


;; --- req/rep ---

(define-test req/rep-tcp-single-endpoint-auth-nil :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-ipc-single-endpoint-auth-nil :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-inproc-single-endpoint-auth-nil :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)))
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))


;; auth bytes type

(define-test req/rep-tcp-single-endpoint-auth-bytes :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-ipc-single-endpoint-auth-bytes :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-inproc-single-endpoint-auth-bytes :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)))
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))


;; auth string type

(define-test req/rep-tcp-single-endpoint-auth-string :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-ipc-single-endpoint-auth-string :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :ipc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)) 'condition)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

(define-test req/rep-inproc-single-endpoint-auth-string :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :inproc)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-auth)))
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes nil client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj nil client-auth))
           (obj (easy-zeromq::decode ret-bytes)))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoints str nil client-wrong-auth)))
    (sleep 0.01)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))


;; multiple endpoints

(define-test req/rep-tcp-multi-endpoints-auth-nil :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-ipc-multi-endpoints-auth-nil :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-inproc-multi-endpoints-auth-nil :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-tcp-multi-endpoints-auth-bytes :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-ipc-multi-endpoints-auth-bytes :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-inproc-multi-endpoints-auth-bytes :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-bytes*)
         (client-auth *client-auth-bytes*)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-tcp-multi-endpoints-auth-string :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :tcp)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-ipc-multi-endpoints-auth-string :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :ipc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (fail (bt:with-timeout (1) (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)) 'condition)
               (is eql nil (pop *msg-stack*))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))

(define-test req/rep-inproc-multi-endpoints-auth-string :parent req/rep
  (let* ((num 5)
         (ports (loop repeat num collect (easy-zeromq::gen-random-port)))
         (protocal :inproc)
         (listens (loop for port in ports collect (easy-zeromq::gen-listen-address protocal nil port)))
         (endpoints (if (eq protocal :tcp)
                        (loop for port in ports collect (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port))
                        listens))
         (server-auth *server-auth-string*)
         (client-auth *client-auth-string*)
         (client-wrong-auth *client-wrong-auth-string*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (loop for endpoint in endpoints
          do (progn
               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (is equalp bytes (easy-zeromq::req-send-bytes endpoint bytes nil client-auth))
               (sleep 0.1)
               (is equalp bytes (pop *msg-stack*))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint class-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-class obj)
                 (is =     (a obj) (a class-obj))
                 (is equal (b obj) (b class-obj)))
               (let ((class (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type  %test-encoding-class class)
                 (is =     (a class) (a class-obj))
                 (is equal (b class) (b class-obj)))

               (let* ((ret-bytes (easy-zeromq::req-send-object endpoint struct-obj nil client-auth))
                      (obj (easy-zeromq::decode ret-bytes)))
                 (of-type  %test-encoding-struct obj)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
               (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
                 (of-type %test-encoding-struct struct)
                 (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
                 (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

               (is equal str (flexi-streams:octets-to-string (easy-zeromq::req-send-string endpoint str nil client-wrong-auth)))
               (sleep 0.1)
               (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

               (easy-zeromq::with-req-client (sender endpoint client-auth)
                 (pzmq:send sender str)
                 (pzmq:with-message msg
                   (pzmq:msg-recv msg sender)
                   (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
                 (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
               ))))










;; --- router/dealer with dealer client, reply test ---

(define-test reply-router/dealer-tcp-single-endpoint-auth-nil :parent router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (reply-handler #'replied-msg-handler)
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Router dealer server listens: ~s~%" listens)
    (format t "~%Dealer client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::dealer-send-string endpoints str reply-handler client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    ;; this test cannot use reply-handler binded in let as the msg cannot decode
    (is equalp bytes (easy-zeromq::dealer-send-bytes endpoints bytes (lambda (x) x) client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (of-type %test-encoding-class (easy-zeromq::dealer-send-object endpoints class-obj reply-handler client-auth))
    (sleep 0.1)
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (of-type %test-encoding-struct (easy-zeromq::dealer-send-object endpoints struct-obj reply-handler client-auth))
    (sleep 0.01)
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (easy-zeromq::dealer-send-string endpoints str reply-handler client-wrong-auth t))
    (sleep 0.1)
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-dealer-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (sleep 0.1)
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg)))))
    ))


;; --- req/rep reply test ---

(define-test reply-req/rep-tcp-single-endpoint-auth-nil :parent req/rep
  (let* ((port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (reply-handler #'replied-msg-handler)
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-req-rep-server #'rep-message-handler-reply listens server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::req-send-string endpoints str #'flexi-streams:octets-to-string client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes (lambda (x) x) client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj reply-handler client-auth))
           (obj ret-bytes))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj reply-handler client-auth))
           (obj ret-bytes))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (easy-zeromq::req-send-string endpoints str reply-handler client-wrong-auth t))
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))

;; router/dealer with req client test

(define-test reply-router/dealer-tcp-single-endpoint-auth-nil :parent req-router/dealer
  (let* ((workers 4)
         (port (easy-zeromq::gen-random-port))
         (protocal :tcp)
         (listens (easy-zeromq::gen-listen-address protocal nil port))
         (endpoints (if (eq protocal :tcp)
                        (easy-zeromq::gen-listen-address protocal (easy-zeromq::get-local-ip) port)
                        listens))
         (reply-handler #'replied-msg-handler)
         (server-auth nil)
         (client-auth nil)
         (client-wrong-auth *client-wrong-auth-bytes*)
         (str        "abcdefg")
         (bytes      (make-array 5 :element-type '(unsigned-byte 8) :initial-contents (list 1 2 3 4 5)))
         (class-obj  (make-instance '%test-encoding-class :a 1 :b "abc"))
         (struct-obj (make-test-encoding-struct :a 1 :b "abc")))
    (format t "~%Reply server listens: ~s~%" listens)
    (format t "~%Request client endpoint: ~s~%" endpoints)
    (easy-zeromq::start-router-dealer-server #'dealer-message-handler-reply listens workers server-auth)
    (format t "~&Wait to start the server!~%")
    (sleep 1)

    (easy-zeromq::req-send-string endpoints str #'flexi-streams:octets-to-string client-auth)
    (sleep 0.1)
    (is equal str (flexi-streams:octets-to-string (pop *msg-stack*)))

    (is equalp bytes (easy-zeromq::req-send-bytes endpoints bytes (lambda (x) x) client-auth))
    (sleep 0.1)
    (is equalp bytes (pop *msg-stack*))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints class-obj reply-handler client-auth))
           (obj ret-bytes))
      (of-type  %test-encoding-class obj)
      (is =     (a obj) (a class-obj))
      (is equal (b obj) (b class-obj)))
    (let ((class (easy-zeromq::decode (pop *msg-stack*))))
      (of-type  %test-encoding-class class)
      (is =     (a class) (a class-obj))
      (is equal (b class) (b class-obj)))

    (let* ((ret-bytes (easy-zeromq::req-send-object endpoints struct-obj reply-handler client-auth))
           (obj ret-bytes))
      (of-type  %test-encoding-struct obj)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a obj))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b obj)))
    (let ((struct (easy-zeromq::decode (pop *msg-stack*))))
      (of-type %test-encoding-struct struct)
      (is =     (%test-encoding-struct-a struct-obj) (%test-encoding-struct-a struct))
      (is equal (%test-encoding-struct-b struct-obj) (%test-encoding-struct-b struct)))

    (fail (easy-zeromq::req-send-string endpoints str reply-handler client-wrong-auth t))
    (is eql nil (pop *msg-stack*))

    (easy-zeromq::with-req-client (sender endpoints client-auth)
      (pzmq:send sender str)
      (pzmq:with-message msg
        (pzmq:msg-recv msg sender)
        (is equal str (flexi-streams:octets-to-string (easy-zeromq::unpack-foreign-msg-to-bytes msg))))
      (is equal str (flexi-streams:octets-to-string (pop *msg-stack*))))
    ))
